home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / dpmigcc5.zip / RSX / SOURCE / SIGNALS3.C < prev    next >
C/C++ Source or Header  |  1994-12-12  |  17KB  |  640 lines

  1. /*****************************************************************************
  2.  * FILE: signals.c                                 *
  3.  *                                         *
  4.  * DESC:                                     *
  5.  *    - signal handling                             *
  6.  *    - exception handler                             *
  7.  *    - DPMI 1.0 page fault handler                         *
  8.  *                                         *
  9.  * Copyright (C) 1993,1994                             *
  10.  *    Rainer Schnitker, Heeper Str. 283, 33607 Bielefeld             *
  11.  *    email: rainer@mathematik.uni-bielefeld.de                 *
  12.  *                                         *
  13.  *****************************************************************************/
  14.  
  15. #include <string.h>
  16. #include "PRINTF.H"
  17. #include "DPMI.H"
  18. #include "DPMI10.H"
  19. #include "RMLIB.H"
  20. #include "PROCESS.H"
  21. #include "SIGNALS.H"
  22. #include "START32.H"
  23. #include "CDOSX32.H"
  24. #include "EXCEP32.H"
  25. #include "ADOSX32.H"
  26. #include "COPY32.H"
  27. #include "RSX.H"
  28. #include "LOADPRG.H"
  29. #include "KDEB.H"
  30. #include "DOSERRNO.H"
  31.  
  32. #define SIGSA(no)   ((no)-1)
  33. #define SIGMASK(no) (1L<<((no)-1))
  34. #define SIGBLOCK    (~(SIGSA(SIGKILL)))
  35.  
  36. #define SA_NOTBSD   (SA_SYSV | SA_ACK)
  37.  
  38. /* local functions */
  39. static int exception2signal(WORD);
  40. static int do_signal(DWORD);
  41. static void print_exception_exit(void);
  42. static void print_regs_exception(void);
  43.  
  44. /* regs after exceptions */
  45. REG386 regf;
  46. extern char *sigtext[];
  47.  
  48. /*
  49. ** give back a signal no from a hardware exception fault no
  50. */
  51. static int exception2signal(WORD faultno)
  52. {
  53.     int signal;
  54.  
  55.     switch (faultno) {
  56.     case 0:
  57.     case 2:
  58.     case 4:
  59.     case 5:
  60.     case 6:
  61.     case 8:
  62.     case 10:
  63.     case 15:
  64.     signal = SIGILL;
  65.     break;
  66.     case 1:
  67.     case 3:
  68.     signal = SIGTRAP;
  69.     break;
  70.     case 7:
  71.     case 16:
  72.     signal = SIGFPE;
  73.     break;
  74.     case 9:
  75.     case 11:
  76.     case 12:
  77.     case 13:
  78.     case 14:
  79.     case 17:
  80.     signal = SIGSEGV;
  81.     break;
  82.     default:
  83.     signal = SIGSEGV;
  84.     break;
  85.     }
  86.  
  87.     return signal;
  88. }
  89.  
  90. /*
  91. ** set signal for one process
  92. */
  93. int send_signal(NEWPROCESS * p, int signal)
  94. {
  95.     if (!p || signal < 0 || signal >= MAX_SIGNALS)
  96.     return EMX_EINVAL;
  97.     p->sig_raised |= SIGMASK(signal);
  98.     return 0;
  99. }
  100.  
  101. static void check_pending(int signum)
  102. {
  103.     struct sigaction *p;
  104.  
  105.     p = signum - 1 + npz->sigaction;
  106.     if (p->sa_handler == SIG_IGN) {
  107.     if (signum == SIGCHLD)
  108.         return;
  109.     npz->sig_raised &= ~ SIGMASK(signum);
  110.         return;
  111.     }
  112.     if (p->sa_handler == SIG_DFL) {
  113.     if (signum != SIGCHLD)
  114.         return;
  115.     npz->sig_raised &= ~ SIGMASK(signum);
  116.     return;
  117.     }
  118. }
  119.  
  120. int sys_sigaction(int signum, DWORD action, DWORD oldaction)
  121. {
  122.     struct sigaction new_sa, *p;
  123.  
  124.     if (signum<1 || signum>=MAX_SIGNALS || signum==SIGKILL)
  125.     return -EMX_EINVAL;
  126.     p = signum - 1 + npz->sigaction;
  127.     if (action) {
  128.     if (verify_illegal(npz, action, sizeof(action)))
  129.         return -EMX_EINVAL;
  130.     cpy32_16(npz->data32sel, action, &new_sa, sizeof(struct sigaction));
  131.     new_sa.sa_mask |= SIGMASK(signum);
  132.     new_sa.sa_mask &= SIGBLOCK;
  133.     }
  134.     if (oldaction) {
  135.     if (verify_illegal_write(npz, oldaction, sizeof(oldaction)))
  136.         return -EMX_EINVAL;
  137.     cpy16_32(npz->data32sel, oldaction, p, sizeof(struct sigaction));
  138.     }
  139.     if (action) {
  140.     *p = new_sa;
  141.     check_pending(signum);
  142.     }
  143.     return 0;
  144. }
  145.  
  146. int sys_sigpending(DWORD set_addr)
  147. {
  148.     DWORD set = npz->sig_blocked & npz->sig_raised;
  149.  
  150.     if (verify_illegal_write(npz, set, 4))
  151.     return -EMX_EINVAL;
  152.     store32(npz->data32sel, set_addr, set);
  153.     return 0;
  154. }
  155.  
  156. int sys_sigprocmask(int how, DWORD set, DWORD oset)
  157. {
  158.     sigset_t new_set, old_set = npz->sig_blocked;
  159.  
  160.     if (set) {
  161.     if (verify_illegal(npz, set, sizeof(sigset_t)))
  162.         return -EMX_EINVAL;
  163.     new_set = read32(npz->data32sel, set) & SIGBLOCK;
  164.  
  165.     switch (how) {
  166.         case SIG_BLOCK:
  167.         npz->sig_blocked |= new_set;
  168.         break;
  169.         case SIG_UNBLOCK:
  170.         npz->sig_blocked &= ~new_set;
  171.         break;
  172.         case SIG_SETMASK:
  173.         npz->sig_blocked = new_set;
  174.         break;
  175.         default:
  176.         return -EMX_EINVAL;
  177.     }
  178.     }
  179.     if (oset) {
  180.     if (verify_illegal_write(npz, oset, sizeof(sigset_t)))
  181.         return -EMX_EINVAL;
  182.     store32(npz->data32sel, oset, old_set);
  183.     }
  184.     return 0;
  185. }
  186.  
  187. /*
  188. ** signal handler returned via syscall 0x10
  189. */
  190. int signal_handler_returned(void)
  191. {
  192.     DWORD signal, sig_blocked;
  193.     DWORD r;
  194.  
  195.     signal = read32(npz->data32sel, ESPORG);
  196.     if (opt_printall)
  197.     printf("return signal handler: %lX\n", signal);
  198.  
  199.     sig_blocked = read32(npz->data32sel, ESPORG + 4);
  200.  
  201.     /* unblock old signal mask, if not emx ack */
  202.     if (!(npz->sigaction[SIGSA(signal)].sa_flags & SA_ACK))
  203.     npz->sig_blocked = sig_blocked & ~SIGMASK(signal);
  204.  
  205.     r = read32(npz->data32sel, ESPORG + 8);    /* nop ; mov $7f10, %eax */
  206.     if (r != 0x7F10b890) {
  207.     puts("illegal frame");
  208.     return 1;
  209.     }
  210.     r = read32(npz->data32sel, ESPORG + 12);     /* int 0x21 */
  211.     if (r != 0x21cd0000) {
  212.     puts("illegal frame");
  213.     return 1;
  214.     }
  215.  
  216.     cpy32_16(npz->data32sel, ESPORG + 16, &(npz->regs), sizeof(REG386));
  217.  
  218.     if (AX == 0x7f0E) {     /* back from raise() */
  219.     EAX = ECX = 0;        /* put return values */
  220.     back_from_syscall();
  221.     return 1;
  222.     }
  223.     /*
  224.     ** if we had a hardware exception, we zero the user handler, to
  225.     ** prevent a exception loop to handler (may be changed in future)
  226.     */
  227.     if (signal == SIGSEGV || signal == SIGILL ||
  228.     signal == SIGFPE || signal == SIGTRAP)
  229.     (npz->sigaction[SIGSA(signal)]).sa_handler = 0;
  230.  
  231.     return 1;
  232. }
  233.  
  234. /*
  235. ** called before return to user process
  236. */
  237. int check_signals(void)
  238. {
  239.     do_signal(npz->sig_blocked);
  240.     return 0;
  241. }
  242.  
  243. #define SIGDFL_IGNORE        0
  244. #define SIGDFL_TERMINATE    1
  245. #define SIGDFL_CORE        2
  246.  
  247. static struct {
  248.     char *text;
  249.     char action;
  250. } sigdfl[MAX_SIGNALS] = {
  251.     { "SIGHUP",     SIGDFL_TERMINATE },
  252.     { "SIGINT",     SIGDFL_TERMINATE },
  253.     { "SIGQUIT",    SIGDFL_CORE },
  254.     { "SIGILL",     SIGDFL_CORE },
  255.     { "SIGTRAP",    SIGDFL_CORE },
  256.     { "SIGABRT",    SIGDFL_CORE },
  257.     { "SIGEMT",     SIGDFL_CORE },
  258.     { "SIGFPE",     SIGDFL_CORE },
  259.     { "SIGKILL",    SIGDFL_TERMINATE },
  260.     { "SIGBUS",     SIGDFL_CORE },
  261.     { "SIGSEGV",    SIGDFL_CORE },
  262.     { "SIGSYS",     SIGDFL_CORE },
  263.     { "SIGPIPE",    SIGDFL_TERMINATE },
  264.     { "SIGALRM",    SIGDFL_TERMINATE },
  265.     { "SIGTERM",    SIGDFL_TERMINATE },
  266.     { "SIGUSR1",    SIGDFL_IGNORE },
  267.     { "SIGUSR2",    SIGDFL_IGNORE },
  268.     { "SIGCHLD",    SIGDFL_IGNORE },
  269.     { "SIG19",      SIGDFL_IGNORE },
  270.     { "SIG20",      SIGDFL_IGNORE },
  271.     { "SIGBREAK",   SIGDFL_TERMINATE }
  272. };
  273.  
  274. void setup_frame(DWORD address, DWORD oldmask, int signal)
  275. {
  276.     DWORD code;
  277.  
  278.     if (ESP == ESPORG)        /* build stack-frame,if not */
  279.     ESP -= 12;
  280.  
  281.     /* save regs for handler return, put reg values on user stack */
  282.     cpy16_32(npz->data32sel, ESP - sizeof(REG386),
  283.          &(npz->regs), sizeof(REG386));
  284.     ESP -= sizeof(REG386);    /* sub register-frame */
  285.  
  286.     EIP = address;        /* sighandler address */
  287.  
  288.     ESP -= sizeof(long);    /* put code: int 0x21 */
  289.     store32(npz->data32sel, ESP, 0x21cd0000);
  290.     ESP -= sizeof(long);    /* put code: popl %eax ; movl $10, %eax */
  291.     store32(npz->data32sel, ESP, 0x7F10b890);
  292.     code = ESP;
  293.  
  294.     ESP -= sizeof(long);    /* put signal mask on user stack */
  295.     store32(npz->data32sel, ESP, oldmask);
  296.     ESP -= sizeof(long);    /* put signalno on user stack */
  297.     store32(npz->data32sel, ESP, signal);
  298.     ESP -= sizeof(long);    /* put return address: stack code */
  299.     store32(npz->data32sel, ESP, code);
  300.  
  301.     ESPORG = ESP;
  302.     ESP -= 12;            /* sub iret frame */
  303. }
  304.  
  305. /*
  306. ** check signals settings , change eip to signal handler
  307. */
  308. static int do_signal(DWORD oldmask)
  309. {
  310.     unsigned long mask = ~npz->sig_blocked;
  311.     unsigned long handler_signal = 0;
  312.     unsigned long signr;
  313.     struct sigaction * sa;
  314.  
  315.     while ((signr = npz->sig_raised & mask)) {
  316.     __asm__("bsf %2,%1\n\t"
  317.         "btrl %1,%0"
  318.         :"=m" (npz->sig_raised),"=r" (signr)
  319.         :"1" (signr));
  320.     sa = npz->sigaction + signr;
  321.     signr++;
  322. #ifdef CONFIG_KDEB
  323.     if (!opt_kdeb)
  324. #endif
  325.     if ((npz->p_flags & PF_DEBUG) && signr != SIGKILL && signr != SIGCLD) {
  326.         npz->p_status = PS_STOP;
  327.         npz->wait_return = (signr << 8) | 127;
  328.         npz->p_flags |= PF_WAIT_WAIT;
  329.         npz->pptr->p_status = PS_RUN;
  330.         switch_context(npz->pptr);
  331.         if (npz->code32sel == 0) {
  332.         puts("child killed");
  333.         switch_context(npz->pptr);
  334.         shut_down(0);
  335.         }
  336.         if (SIGMASK(signr) & npz->sig_blocked) {
  337.         npz->sig_raised |= SIGMASK(signr);
  338.         continue;
  339.         }
  340.         sa = npz->sigaction + signr - 1;
  341.     }
  342.     if (sa->sa_handler == SIG_IGN) {
  343.         unsigned dummy;
  344.         if (signr != SIGCHLD)
  345.         continue;
  346.         /* check for SIGCHLD: wait for processes */
  347.         while (sys_wait(&dummy) > 0)
  348.         ;
  349.         continue;
  350.     }
  351.     if (sa->sa_handler == SIG_DFL) {
  352.         /* emx ignores SIGCLD, SIGCHLD, SIGUSR */
  353.  
  354.         if (sigdfl[SIGSA(signr)].action == SIGDFL_IGNORE)
  355.         continue;
  356.         else if (sigdfl[SIGSA(signr)].action == SIGDFL_CORE)
  357.         if (!opt_nocore)
  358.             write_core_file(npz);
  359.  
  360.         printf("\nProcess terminated by %s\n", sigdfl[SIGSA(signr)].text);
  361.  
  362.         do_exit4c(signr);
  363.         return 1;
  364.     }
  365.     handler_signal |= 1 << (signr-1);
  366.     mask &= ~sa->sa_mask;
  367.     }
  368.  
  369.     if (!handler_signal)    /* no handler will be called - return 0 */
  370.     return 0;
  371.  
  372.     if (opt_printall)
  373.     printf("signals = %lX\n", handler_signal);
  374.  
  375.     signr = 1;
  376.     sa = npz->sigaction;
  377.     for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
  378.     if (mask > handler_signal)
  379.         break;
  380.     if (!(mask & handler_signal))
  381.         continue;
  382.         setup_frame(sa->sa_handler, oldmask | SIGMASK(signr), signr);
  383.     if (sa->sa_flags & SA_SYSV)
  384.         sa->sa_handler = 0L;
  385.     else
  386.         npz->sig_blocked |= sa->sa_mask;   /* set blocked */
  387.     oldmask |= sa->sa_mask;
  388.     }
  389.     return 1;
  390. }
  391.  
  392. long sys_signal(int signum, long handler)
  393. {
  394.     long old_handler;
  395.  
  396.     if (signum < 1 || signum >= MAX_SIGNALS || signum == SIGKILL)
  397.     return -1;
  398.  
  399.     old_handler = npz->sigaction[SIGSA(signum)].sa_handler;
  400.  
  401.     if (handler == SIG_ACK) {
  402.     npz->sig_blocked &= ~ SIGMASK(signum);
  403.     return old_handler;
  404.     }
  405.     else if (handler != SIG_DFL && handler != SIG_IGN)
  406.     if (verify_illegal(npz, handler, 4))
  407.         return -1;
  408.  
  409.     npz->sigaction[SIGSA(signum)].sa_handler = handler;
  410.     npz->sigaction[SIGSA(signum)].sa_flags = 0;
  411.     npz->sigaction[SIGSA(signum)].sa_mask = 0;
  412.  
  413.     if ((npz->uflags & 3) == 1)     /* system V */
  414.     npz->sigaction[SIGSA(signum)].sa_flags = SA_SYSV;
  415.     else if ((npz->uflags & 3) == 2)    /* BSD */
  416.     npz->sigaction[SIGSA(signum)].sa_flags = 0;
  417.     else                /* old EMX */
  418.     npz->sigaction[SIGSA(signum)].sa_flags = SA_ACK;
  419.  
  420.     return old_handler;
  421. }
  422.  
  423. char *exceptext[] =
  424. {
  425.     "division by zero",
  426.     "debug",
  427.     "NMI",
  428.     "breakpoint",
  429.     "overflow",
  430.     "bound check",
  431.     "invalid opcode",
  432.     "copro not availble",
  433.     "double fault",
  434.     "copro exception",
  435.     "invalid TSS",
  436.     "segment not present",
  437.     "stack fault",
  438.     "general protection",
  439.     "page fault",
  440.     "reserved",
  441.     "copro error",
  442.     "alignment error"
  443. };
  444.  
  445.  
  446. /*
  447. ** this function is called after hardware exceptions
  448. */
  449.  
  450. EXCEPTION_10 reg_info;
  451.  
  452. void myexcep13(void)
  453. {                /* C exception handler */
  454.     int signal;
  455.  
  456. #ifdef CONFIG_KDEB
  457.     if (opt_kdeb && (WORD) regf.cs == code16sel && regf.faultno == 1) {
  458.     memcpy(&(RSX_PROCESS.regs), ®f, sizeof(REG386));
  459.     return KDEB_debug_handler();
  460.     }
  461. #endif
  462.  
  463.     if (opt_printall)
  464.     printf("Exception %d\n", (WORD) regf.faultno);
  465.  
  466.     /* test if we have a error in kernel, abort rsx */
  467.     /* future versions will just terminate the running process */
  468.  
  469.     if ((WORD) regf.cs == code16sel || (WORD) regf.ds == data16sel) {
  470.     printf("Kernel fault at %X %lX\n", (WORD) regf.cs, regf.eip);
  471.     printf("EAX=%08lX EBX=%08lX ECX=%08lX EDX=%08lX\n"
  472.            "EBP=%08lX ESP=%08lX  ESI=%08lX EDI=%08lX\n"
  473.            "CS=%04X DS=%04X ES=%04X SS=%04X\n",
  474.            regf.eax, regf.ebx, regf.ecx, regf.edx,
  475.            regf.ebp, regf.esp, regf.esi, regf.edi,
  476.      (WORD) regf.cs, (WORD) regf.ds, (WORD) regf.es, (WORD) regf.ss);
  477.     if (dpmi10) {
  478.         printf("cr2 = %lX\n", reg_info.cr2);
  479.         printf("pte = %lX\n", reg_info.pte);
  480.     }
  481.     printf("User Registers:\n");
  482.     npz->regs.faultno = regf.faultno;
  483.     print_exception_exit();
  484.     }
  485.  
  486.     /* user fault, copy saved regs to process table */
  487.     memcpy(&(npz->regs), ®f, sizeof(REG386));
  488.  
  489.     signal = exception2signal(FAULTNO);
  490.  
  491.     if (signal != SIGTRAP) {
  492.     printf("process %d get hardware fault %d (%s) at %lX\n",
  493.            npz->pid, FAULTNO, exceptext[FAULTNO], EIP);
  494.     if (opt_printall) {
  495.         print_regs_exception();
  496.         if (dpmi10) {
  497.         printf("cr2 = %lX\n", reg_info.cr2);
  498.         printf("offset = %lX\n", reg_info.cr2 - npz->memaddress);
  499.         printf("pte = %lX\n", reg_info.pte);
  500.         }
  501.     }
  502.     }
  503.     send_signal(npz, signal);
  504.  
  505.     /* then, check_signal() is called (see excep32.asm) */
  506. }
  507.  
  508. static void print_regs_exception(void)
  509. {
  510.     printf("selector=%lX  errbits: %X\n"
  511.        "cs:eip=%04X:%08lX eflags=%08lX\n"
  512.        "eax=%08lX ebx=%08lX ecx=%08lX edx=%08lX\n"
  513.        "ebp=%08lX esp=%08lX  esi=%08lX edi=%08lX\n"
  514.        "cs=%04X ds=%04X es=%04X ss=%04X fs=%04X gs=%04X\n",
  515.        ERR & ~7L, (WORD) ERR & 7,
  516.        CS, EIP, EFLAGS,
  517.        EAX, EBX, ECX, EDX,
  518.        EBP, ESP, ESI, EDI,
  519.        CS, DS, ES, SS, FS, GS);
  520. }
  521.  
  522. static void print_exception_exit()
  523. {
  524.     printf("PROTECTION FAULT  %d :\n", FAULTNO);
  525.     print_regs_exception();
  526.     shut_down(3);
  527. }
  528.  
  529.  
  530. /*
  531. ** DPMI 1.0 support, damand paging
  532. **
  533. ** only called, if start32.c sets page_fault() function
  534. */
  535.  
  536. /*
  537. ** commit page, if legal address
  538. ** page in text, data
  539. ** return 1, if real page-fault
  540. */
  541.  
  542. static unsigned char pagein_buffer[4096];
  543.  
  544. int swapper(void)
  545. {
  546.     DWORD offset;
  547.     NEWPROCESS *proc;
  548.     WORD page = 1 + 8;        /* commit & read/write */
  549.     int handle;
  550.  
  551.     if ((WORD) reg_info.cs == code16sel) {
  552.     /* copy in kernel, find current process */
  553.     for (proc = &FIRST_PROCESS; proc <= &LAST_PROCESS; proc++) {
  554.         if (!proc->code32sel)
  555.         continue;
  556.         if ((reg_info.cr2 > proc->memaddress) &&
  557.         (reg_info.cr2 < proc->memaddress + proc->membytes))
  558.         break;
  559.     }
  560.     if (proc > &LAST_PROCESS) {
  561.         if (opt_printall) {
  562.         puts("swapper: cannot find process");
  563.         printf("pagefault in %04X\n", (WORD) reg_info.cs);
  564.         printf("cr2 %08lX\n", reg_info.cr2);
  565.         printf("pte %X err %X\n", (WORD) reg_info.pte, (WORD) reg_info.error_code);
  566.         }
  567.         return 1;
  568.     }
  569.     } else
  570.     proc = npz;
  571.  
  572.     offset = (reg_info.cr2 - proc->memaddress) & ~0xFFFL;
  573.  
  574. #if 0
  575.     if (opt_printall) {
  576.     printf("process %d : pagefault in %04X\n", proc->pid, (WORD) reg_info.cs);
  577.     printf("cr2 %08lX, pageoffset %08lX\n", reg_info.cr2, offset);
  578.     printf("pte %X err %X\n", (WORD) reg_info.pte, (WORD) reg_info.error_code);
  579.     printf("memaddress = %lX handle = %lX\n", proc->memaddress, proc->memhandle);
  580.     }
  581. #endif
  582.  
  583.     if (proc->pid == 0)
  584.     return 1;
  585.  
  586.     handle = (int) proc->filehandle;
  587.  
  588.     /* text */
  589.     if (offset >= proc->text_start && offset < proc->text_end) {
  590.     if ((WORD) reg_info.cs != code16sel && (reg_info.error_code & 2))
  591.         return 1;
  592.     if (ModifyPageAttributes(proc->memhandle, offset, 1, &page))
  593.         return 1;        /* better:readonly */
  594.     if (handle == 0)    /* forked process */
  595.         return 0;
  596.     rm_lseek(handle, proc->text_off + (offset - proc->text_start), SEEK_SET);
  597.     if (rm_read(handle, pagein_buffer, 4096) != 4096)
  598.         return 1;
  599.     cpy16_32(proc->data32sel, offset, pagein_buffer, 4096L);
  600.     page = 1;
  601.     if (ModifyPageAttributes(proc->memhandle, offset, 1, &page))
  602.         return 1;
  603.     return 0;
  604.     } else
  605.      /* bss */ if (offset >= proc->bss_start && offset < proc->bss_end) {
  606.     if (ModifyPageAttributes(proc->memhandle, offset, 1, &page))
  607.         return 1;
  608.     if (handle == 0)    /* forked process */
  609.         return 0;
  610.     bzero32(proc->data32sel, offset, 4096L);
  611.     return 0;
  612.     } else
  613.      /* data */ if (offset >= proc->data_start && offset < proc->data_end) {
  614.     if (ModifyPageAttributes(proc->memhandle, offset, 1, &page))
  615.         return 1;
  616.     if (handle == 0)    /* forked process */
  617.         return 0;
  618.     rm_lseek(handle, proc->data_off + (offset - proc->data_start), SEEK_SET);
  619.     if (rm_read(handle, pagein_buffer, 4096) != 4096)
  620.         return 1;
  621.     cpy16_32(proc->data32sel, offset, pagein_buffer, 4096L);
  622.     return 0;
  623.     } else
  624.      /* heap */ if (offset >= proc->init_brk && offset < proc->brk_value) {
  625.     if (ModifyPageAttributes(proc->memhandle, offset, 1, &page))
  626.         return 1;
  627.     if (handle == 0)    /* forked process */
  628.         return 0;
  629.     if (proc->p_flags & PF_DJGPP_FILE)
  630.         bzero32(proc->data32sel, offset, 4096L);
  631.     return 0;
  632.     } else
  633.      /* stack */ if (offset >= proc->brk_value && offset <= proc->membytes) {
  634.     if (ModifyPageAttributes(proc->memhandle, offset, 1, &page))
  635.         return 1;
  636.     return 0;
  637.     } else
  638.     return 1;
  639. }
  640.